package work.mediway.mdm.biz.util;

import com.mediway.hos.common.utils.ExceptionUtil;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 解决部分mybatis plus问题。
 *
 * @author ruoyi
 * @since 2022-08-25
 */
@Slf4j
@Component
public class MybatisPlusUtil {

    private static String LAST_UPDATE_DATE_SUFFIX = "LastUpdateDate";
    private static String LAST_UPDATE_TIME_SUFFIX = "LastUpdateTime";
    private static String LAST_UPDATE_USER_SUFFIX = "LastUpdateUser";
    private static String CREATE_DATE_SUFFIX = "CreateDate";
    private static String CREATE_TIME_SUFFIX = "CreateTime";
    private static String CREATE_USER_SUFFIX = "CreateUser";

    /**
     * 设置实体类的创建信息，因为在数据库中，这些字段有相同的名称后缀
     *
     * @param object 实体类
     * @param user   用户名
     */
    public static void setCreateInfo(Object object, String user) {
        Map<String, Object> createAttrVal = new HashMap<>();
        createAttrVal.put(CREATE_DATE_SUFFIX,DateUtil.now());
        createAttrVal.put(CREATE_TIME_SUFFIX,DateUtil.now());
        createAttrVal.put(CREATE_USER_SUFFIX,user);
        for (Field field : ReflectUtil.getFields(object.getClass())) {
            setterInvoker(object,field,createAttrVal);
        }
        setUpdateInfo(object, user);
    }

    /**
     * 设置实体类的更新信息，因为在数据库中，这些字段有相同的名称后缀
     *
     * @param object
     * @param user   用户名
     */
    public static void setUpdateInfo(Object object, String user) {
        Map<String, Object> updateAttrVal = new HashMap<>();
        updateAttrVal.put(LAST_UPDATE_DATE_SUFFIX,DateUtil.now());
        updateAttrVal.put(LAST_UPDATE_TIME_SUFFIX,DateUtil.now());
        updateAttrVal.put(LAST_UPDATE_USER_SUFFIX,user);
        for (Field field : ReflectUtil.getFields(object.getClass())) {
            setterInvoker(object,field,updateAttrVal);
        }
    }

    /**
     * 调用对象的setter方法
     *
     * @param object    目标对象
     * @param field     具体字段
     * @param attrVal 字段名->要设置的值
     */
    public static void setterInvoker(Object object, Field field, Map<String, Object> attrVal) {
        String name = field.getName();
        String nameUpperCase = name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
        Class<?> type = field.getType();
        attrVal.forEach((key, value) -> {
            if (StringUtils.endsWith(name, key)) {
                try {
                    //获取属性的set方法
                    Method setter = object.getClass().getMethod("set" + nameUpperCase, type);
                    //设置对应的值
                    setter.invoke(object, value);
                } catch (Exception e) {
                    log.error(ExceptionUtil.getExceptionMessage(e), e);
                }
            }
        });
    }


    /**
     * 判断对象的某些String字段是否为blank，如果有，就设置为null
     * 由于mybatis plus提供的更新、插入策略有限，部分值设为空，不能以空字符串，而要用null
     *
     * @param object       传入对象
     * @param targetFields 需要进行判断的字段数组
     */
    public static void setNullWhenBlank(Object object, String[] targetFields) {
        Field[] fields = ReflectUtil.getFields(object.getClass());
        for (Field field : fields) {
            String name = field.getName();
            //判断是否是模板字段
            if (StringUtils.equalsAny(name, targetFields)) {
                Class<?> type = field.getType();
                //判断是否为String类型
                if (ClassUtil.equals(type, ClassUtil.getClassName(String.class, true), false)) {
                    try {
                        String nameUpperCase = name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
                        //获取get方法
                        Method getter = ReflectUtil.getMethodByName(object.getClass(), "get" + nameUpperCase);
                        String val = String.valueOf(getter.invoke(object, null));
                        //判断是否为blank，是则设为null
                        if (StringUtils.isBlank(val)) {
                            //获取属性的set方法
                            Method setter = object.getClass().getMethod("set" + nameUpperCase, type);
                            //将值设为null
                            setter.invoke(object, new Object[]{null});
                        }
                    } catch (Exception e) {
                        log.error(ExceptionUtil.getExceptionMessage(e), e);
                    }
                }
            }

        }
    }
}
